package com.ray.test.runner;

import com.ray.test.hander.HanderContent;
import com.ray.test.hander.SpringTxHander;
import com.ray.test.util.ClassUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.runners.model.InitializationError;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * @author bo shen
 * @Description: 数据库单元测试
 * @Class: RAutoSpringJUnit4ClassRunner
 * @Package test.runner
 * @date 2019/9/29 8:45
 * @company <p>杭州传化陆鲸科技有限公司</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
public class RDBAutoSpringJUnit4ClassRunner extends SpringJUnit4ClassRunner {

    private static final Log logger = LogFactory.getLog(RDBAutoSpringJUnit4ClassRunner.class);

    private static ThreadLocal<ApplicationContext> applicationContextThreadLocal = new ThreadLocal<>();

    private static ThreadLocal<PlatformTransactionManager> platformTransactionManagerThreadLocal = new ThreadLocal<>();

    private static ThreadLocal<TransactionDefinition> transactionDefinitionThreadLocal = new ThreadLocal<>();

    public RDBAutoSpringJUnit4ClassRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
        ApplicationContext applicationContext = super.getTestContextManager().getTestContext().getApplicationContext();
        applicationContextThreadLocal.set(applicationContext);
        //初始化容器
        PlatformTransactionManager platformTransactionManager = applicationContext.getBean("transactionManager", PlatformTransactionManager.class);
        if (ObjectUtils.isEmpty(platformTransactionManager)) {
            platformTransactionManager = applicationContext.getBean(PlatformTransactionManager.class);
        }
        platformTransactionManagerThreadLocal.set(platformTransactionManager);
        TransactionDefinition transactionDefinition = applicationContext.getBean(TransactionDefinition.class);
        transactionDefinitionThreadLocal.set(transactionDefinition);
    }


    public static int test(String... paths) {
        logger.info("测试路径:{}" + Arrays.toString(paths));
        List<Class<?>> classList = new ArrayList<>();
        for (String path : paths) {
            logger.info("开始测试" + path + "下的类或接口");
            Set<Class<?>> sets = ClassUtil.getClassSet(path);
            classList.addAll(sets);
        }
        return test(classList,new ArrayList<>(),new ArrayList<>());
    }

    public static int test(Class<?> clazz, String... methodNames) {
        return test(Arrays.asList(clazz),Arrays.asList(methodNames),new ArrayList<>());
    }

    public static int test(Class<?> clazz) {
        return test(Arrays.asList(clazz),new ArrayList<>(),new ArrayList<>());
    }

    public static int test(Class<?>... clazzs) {
        return test(Arrays.asList(clazzs),new ArrayList<>(),new ArrayList<>());
    }

    /**
     * 最后执行方法
     * @param
     * @return
     */
    private  static int test(List<Class<?>> classes,List<String> include,List<String> exclude){
        HanderContent handerContent = new HanderContent();
        handerContent.setApplicationContext(applicationContextThreadLocal.get());
        handerContent.setPlatformTransactionManager(platformTransactionManagerThreadLocal.get());
        handerContent.setTransactionDefinition(transactionDefinitionThreadLocal.get());
        handerContent.setRunClasss(classes);
        handerContent.setExcludeMethodName(exclude);
        handerContent.setIncludeMethodName(include);
        return test(handerContent);
    }

    /**
     * 最后执行方法
     * @param
     * @return
     */
    private static int test(HanderContent handerContent){
        return new SpringTxHander(handerContent).runTest();
    }

}
